<?php

namespace App\Models\Admin;

use App\admin\Service\OA;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;

/**
 * @property int10unsigned id
 * @property varchar255 api
 * @property varchar255 call
 * @property int auth
 * @property int10unsigned count
 * @property int10unsigned isrun
 * @property int10unsigned success
 * @property int11unsigned fail
 * @property varchar255 notes
 * @property varchar255 name
 * @property int11unsigned runtime
 */
class ApilistModel extends BaseModel
{
    /**
     * 管理员
     */

    protected $table = 'apilist';
    protected $fillable = [
        'id', 'api', 'call', 'auth', 'count', 'isrun', 'success', 'fail',
        'notes', 'name', 'runtime',
    ];

    const auth_all = 0;///无权限要求，任何用户可以使用
    const auth_user = 1;///必须是登录用户
    const auth_role = 2;///根据角色组决定


    public static function getAuthArray($key = null)
    {
        $list = [
            self::auth_all => '全部',
            self::auth_user => '登录用户',
            self::auth_role => '角色组'
        ];
        if ($key === null) {
            return $list;
        } else {
            return isset($list[$key]) ? $list[$key] : $key;
        }
    }

    public function attributeLabels()
    {
        return [
            'id' => 'id',
            'api' => '接口字符串',
            'call' => '调用的类和成员',
            'auth' => '授权',//
            'count' => '调用次数',
            'isrun' => '启用',///如果为0，表示禁止执行，非0表示可以执行
            'success' => '成功',
            'fail' => '失败',
            'notes' => '注释',
            'name' => '名字',
            'average_time' => '平均耗时',
            'runtest' => '测试',
            'url'=>'接口地址'
        ];
    }

    public static function callAPI2($strApi, Request $request)
    {
        $apiObj = self::getApiinfo($strApi);
        if(!$apiObj){
            OA::Json(1, '接口调用失败，没有相关接口' . $strApi);
        }
         if ($apiObj['isrun'] == 0) {
            OA::Json(1, '接口调用失败，该接口被禁止使用' . $strApi);
        }
        if ($apiObj['auth'] !== self::auth_all){///如果不是全部授权，则进一步判断
            if (OA::$user->isGuest()) {///如果没有登录，返回授权失败
                OA::Json(OA::Guest, '接口调用失败，没有权限,该接口需要:(' . self::getAuthArray($apiObj['auth']) . ')权限');
            }
            if ($apiObj['auth'] === self::auth_role){///如果是角色组类型
                if (!OA::$user->validateRole($apiObj->id)) {
                    OA::Json(1, '已经登录用户；接口调用失败，没有权限,该接口需要:(' . self::getAuthArray($apiObj['auth']) . ')权限');
                }
            }
        }
        $call = $apiObj['call'];
        if ($call == '') {
            OA::Json(1, '接口调用失败，该接口调用路径为空');
            return;
        }
        $parameter=$apiObj['parameter'];
        $strreturn=$apiObj['strreturn'];
        $postList=[];
        if($parameter&&$parameter!==''&&$parameter!=='[]'){
            $parameterArray=json_decode($parameter,true);
            $postList=self::verification($parameterArray);
        }else{
            $parameter=null;
        }

        $returnArray=[];
        if($strreturn&&$strreturn!==''&&$strreturn!=='[]'){
            $Array=json_decode($strreturn,true);
            foreach ($Array as $vo){
                $returnArray[$vo['Field']]='';
            }
        }

        $isStatic = false;
        $apilist = explode('@', $call);
        if (count($apilist) == 1) {
            $apilist = explode('::', $call);
            if (count($apilist) == 2) {
                $isStatic = true;
            }
        }

        $className = $apilist[0];
        $classCall = isset($apilist[1]) ? $apilist[1] : null;
        if (!class_exists($className)) {
            OA::Json(1, '接口调用失败，接口类不存在' . $className);
        }

        try {


            $isSave = false;
            /**
             * @var $isSuccess 表示是否执行成功，
             */
            OA::RunCall(function ($isSuccess, $content = '') use (&$apiObj, &$isSave, &$beginTime) {
                if ($isSave) {
                    return;
                }
                OA::$_SQL = DB::getQueryLog();
            });
            DB::enableQueryLog();
            $json = [];
            if ($isStatic) {
                $json = $className::$classCall($request,$postList,$returnArray);
            } else {
                $new = new $className($strApi);
                //$new->load();
                if ($classCall) {
                    //var_dump($className,$new,$classCall);exit;
                    $json = $new->$classCall($request,$postList,$returnArray);
                }
            }


            if ($isSave) {
                return;
            }
            OA::$_SQL = DB::getQueryLog();
            $isSave = true;
            OA::Json(0, $json);
        } catch (Exception $e) {
            OA::Json(1, '接口调用失败' . $e->getMessage());
        }
    }
    /**
     * 验证传入信息是否正常,如果不正确返回错苏信息
    */
    public static function verification($parameterArray){
         $post=[];
        foreach ($parameterArray as $vo){
            if(!isset($_POST[$vo['Field']])){
                OA::Json(1,'缺少参数'.$vo['Field']);
            }
            $value=$_POST[$vo['Field']];
            if($vo['Maxlength']!=''&&$vo['Maxlength']!=0){
                if(strlen($value)>$vo['Maxlength']){
                    OA::Json(1,'参数"'.$vo['name'].'"超过接口最大长度限制');
                }
            }
            $post[$vo['Field']]=$_POST[$vo['Field']];
        }
         return $post;
    }
    /**
     * 获取指定接口的信息
     */
    public static function getApiinfo($strApi)
    {
        $apiObj = \Illuminate\Support\Facades\Cache::remember('getApiinfo_' . $strApi, 0, function () use ($strApi) {
            $apiObj = self::where([
                'api' => $strApi
            ])->select([
               'id', 'isrun', 'auth', 'call','parameter','strreturn'
            ])->first();
            if ($apiObj) {
                return $apiObj->toArray();
            }
            return null;
        });

        return $apiObj;
    }


    public static function callAPI($strApi, Request $request)
    {
        $beginTime = microtime(true) * 1000;
        //OA::load();
        /**
         * @var $apiObj ApilistModel
         */
        $apiObj = self::where(['api' => $strApi])->first();
        if (!$apiObj) {
            OA::Json(1, '接口调用失败，没有相关接口' . $strApi);
        }
        if ($apiObj->isrun == 0) {
            /* LogModel::Add($apiObj->id,'接口调用失败，该接口被禁止使用'.$strApi,LogModel::state_fail,
                 microtime(true)*1000-$beginTime);*/
            OA::Json(1, '接口调用失败，该接口被禁止使用' . $strApi);
        }
        //  var_dump($apiObj['name'],$apiObj->auth);exit;
        if ($apiObj->auth !== self::auth_all) {///如果不是全部授权，则进一步判断
            if (OA::$user->isGuest()) {///如果没有登录，返回授权失败
                /* LogModel::Add($apiObj->id,'接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限',
                     LogModel::state_fail,
                     microtime(true)*1000-$beginTime);*/
                OA::Json(OA::Guest, '接口调用失败，没有权限,该接口需要:(' . self::getAuthArray($apiObj->auth) . ')权限');
            }
            if ($apiObj->auth === self::auth_role) {///如果是角色组类型
                if (!OA::$user->validateRole($apiObj->id)) {
                    /*  LogModel::Add($apiObj->id,'已经登录用户；接口调用失败，没有权限,该接口需要:('.self::getAuthArray($apiObj->auth).')权限'
                          ,LogModel::state_fail,
                          microtime(true)*1000-$beginTime);*/
                    OA::Json(1, '已经登录用户；接口调用失败，没有权限,该接口需要:(' . self::getAuthArray($apiObj->auth) . ')权限');
                }
            }

        }

        $apiObj->count++;
        $call = $apiObj->call;
        if ($call == '') {
            $apiObj->fail++;
            $apiObj->runtime += (int)(microtime(true) * 1000 - $beginTime);
            $apiObj->save();
            /*LogModel::Add($apiObj->id,'接口调用失败，该接口调用路径为空'
                ,LogModel::state_fail,
                microtime(true)*1000-$beginTime);*/
            OA::Json(1, '接口调用失败，该接口调用路径为空');
            return;
        }
        $isStatic = false;
        $apilist = explode('@', $call);
        if (count($apilist) == 1) {
            $apilist = explode('::', $call);
            if (count($apilist) == 2) {
                $isStatic = true;
            }
        }

        $className = $apilist[0];
        $classCall = isset($apilist[1]) ? $apilist[1] : null;
        if (!class_exists($className)) {
            /* LogModel::Add($apiObj->id,'接口调用失败，接口类不存在'
                 ,LogModel::state_fail,
                 microtime(true)*1000-$beginTime);*/
            OA::Json(1, '接口调用失败，接口类不存在' . $className);
        }

        try {


            $isSave = false;
            /**
             * @var $isSuccess 表示是否执行成功，
             */
            OA::RunCall(function ($isSuccess, $content = '') use (&$apiObj, &$isSave, &$beginTime) {
                if ($isSave) {
                    return;
                }
                $isSave = true;
                if ($isSuccess) {
                    $apiObj->success++;
                    //  $state=LogModel::state_success;
                } else {
                    $apiObj->fail++;
                    //   $state=LogModel::state_fail;
                }
                // exit('aadsgaf');
                OA::$_SQL = DB::getQueryLog();
                // LogModel::Add($apiObj->id,$content  ,$state, microtime(true)*1000-$beginTime);
                $apiObj->runtime += (int)(microtime(true) * 1000 - $beginTime);
                //  var_dump($apiObj->runtime);exit;
                $apiObj->save();
            });
            DB::enableQueryLog();
            $json = [];
            if ($isStatic) {
                $json = $className::$classCall();
            } else {
                $new = new $className($strApi);
                //$new->load();
                if ($classCall) {
                    //var_dump($className,$new,$classCall);exit;
                    $json = $new->$classCall($request);
                }
            }


            if ($isSave) {
                return;
            }
            OA::$_SQL = DB::getQueryLog();
            $isSave = true;
            $apiObj->success++;
            $apiObj->runtime += microtime(true) * 1000 - $beginTime;
            //  LogModel::Add($apiObj->id,OA::$_apiMsg,LogModel::state_null, microtime(true)*1000-$beginTime);
            $apiObj->save();
            OA::Json(0, $json);
        } catch (Exception $e) {
            $apiObj->fail++;
            $apiObj->runtime += microtime(true) * 1000 - $beginTime;
            //  LogModel::Add($apiObj->id,$e->getMessage() ,LogModel::state_fail, microtime(true)*1000-$beginTime);
            $apiObj->save();
            OA::Json(1, '接口调用失败' . $e->getMessage());
        }
    }


    /**
     * 返回接口测试结果
     */
    public static function getTest($model)
    {
        $apilist = explode('@', $model->call);
        $className = $apilist[0];
        try {
            if (!class_exists($className)) {
                return '接口配置错误，没有找到该类' . $className;
            }
            $new = new $className($className);
            if (!method_exists($new, 'test')) {
                return '接口配置错误，没有继承ApiBase';
            }
            return $new->test();
        } catch (\Exception $e) {
            return '接口配置错误，没有继承ApiBase';
        } catch (ThrowableError $e) {
            return '接口配置错误，没有继承ApiBase';
        }

    }

    /**
     * 返回所有的接口列表
     */
    public static function getList()
    {
        $list = self::where([
            'auth' => self::auth_role
        ])->all();
        $array = [];
        //print_r($list);exit;
        foreach ($list as $item) {
            $array[$item['id']] = $item['name'];
        }
        return $array;
    }


    static $_cachename = [];

    public static function idToName($id)
    {
        if (empty($id)) {
            return '系统';
        }
        if (isset(self::$_cachename[$id])) {
            return self::$_cachename[$id];
        }
        $one = self::find($id);
        if ($one) {
            return self::$_cachename[$id] = $one['name'];
        } else {
            return '接口被删除';
        }
    }
}